package org.university.controller;

import cn.hutool.jwt.JWTUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.university.common.ApiResponse;
import org.university.common.Constant;
import org.university.dto.request.ChangePasswordRequestDTO;
import org.university.dto.request.LoginRequestDTO;
import org.university.dto.request.RegisterStudentRequestDTO;
import org.university.dto.request.RegisterTeacherRequestDTO;
import org.university.dto.response.LoginResponseDTO;
import org.university.dto.response.UserResponseDTO;
import org.university.entity.Student;
import org.university.entity.Teacher;
import org.university.entity.User;
import org.university.exception.*;
import org.university.service.UserService;
import org.university.util.PasswordUtil;
import org.university.util.ValidationUtils;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import static org.university.service.UserService.convertToUserResponseDTO;

/**
 * @Author ：3570023082@qq.com
 * @Date ：2025/9/13 12:27
 * @Description ：登录注册REST Api
 */
@RestController
@RequestMapping("/auth")
public class AuthController {

    private final UserService userService;
    private static final Logger logger = LoggerFactory.getLogger(AuthController.class);

    public AuthController(UserService userService) {
        this.userService = userService;
    }

    /**
     * 学生注册
     */
    @PostMapping("/register/student")
    public ResponseEntity<ApiResponse<UserResponseDTO>> registerStudent(@Validated @RequestBody RegisterStudentRequestDTO registerRequest) {
        try {
            // 调用服务层进行注册
            Student registeredStudent = userService.registerStudent(registerRequest);

            // 转换为响应DTO，避免暴露敏感信息
            UserResponseDTO responseDTO = convertToUserResponseDTO(registeredStudent);

            return ApiResponse.created(responseDTO);
        } catch (UserAlreadyExistsException e) {
            logger.warn("注册失败: {}", e.getMessage());
            return ApiResponse.error(HttpStatus.CONFLICT, e.getMessage());
        } catch (InvalidInputException e) {
            logger.warn("无效注册信息: {}", e.getMessage());
            return ApiResponse.error(HttpStatus.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            logger.error("注册异常: {}", e.getMessage(), e);
            return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, "注册失败，请重试");
        }
    }

    /**
     * 教师注册
     */
    @PostMapping("/register/teacher")
    public ResponseEntity<ApiResponse<UserResponseDTO>> registerTeacher(@Validated @RequestBody RegisterTeacherRequestDTO registerRequest) {
        try {
            // 调用服务层进行注册
            Teacher registeredUser = userService.registerTeacher(registerRequest);

            // 转换为响应DTO，避免暴露敏感信息
            UserResponseDTO responseDTO = convertToUserResponseDTO(registeredUser);

            return ApiResponse.created(responseDTO);
        } catch (UserAlreadyExistsException e) {
            logger.warn("注册失败: {}", e.getMessage());
            return ApiResponse.error(HttpStatus.CONFLICT, e.getMessage());
        } catch (InvalidInputException e) {
            logger.warn("无效注册信息: {}", e.getMessage());
            return ApiResponse.error(HttpStatus.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            logger.error("注册异常: {}", e.getMessage(), e);
            return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, "注册失败，请重试");
        }
    }

    @PostMapping("/login")
    public ResponseEntity<ApiResponse<LoginResponseDTO>> login(@Validated @RequestBody LoginRequestDTO loginRequest) {
        String userId = loginRequest.getUserId();
        String password = loginRequest.getPassword();

        try {
            User user = userService.authenticate(userId, password);

            // token claims
            Map<String, Object> claims = new HashMap<>();
            // JWT jti（JWT ID）字段，用于实现主动注销
            claims.put("jti", UUID.randomUUID().toString());
            claims.put("uid", user.getUserId());
            claims.put("role", user.getRole()); // 用户角色
            long expireSeconds = Constant.getExpireSeconds();
            claims.put("exp", System.currentTimeMillis() / 1000 + expireSeconds);   // 过期时间（时间戳，秒）

            // 获取密钥
            String secretKey = PasswordUtil.getSecretKey();

            // 生成token
            String token = JWTUtil.createToken(claims, secretKey.getBytes());

            // token过期时间
            LocalDateTime expiresTime = LocalDateTime.now().plusSeconds(expireSeconds);
            LocalDateTime loginTime = LocalDateTime.now();

            // 登录返回体
            LoginResponseDTO loginResponse = new LoginResponseDTO(
                    user.getUserId(),
                    user.getUserName(),
                    user.getRole(),
                    token,
                    expiresTime,
                    loginTime
            );

            return ApiResponse.success(loginResponse);

        } catch (UserNotFoundException e) {
            return ApiResponse.error(HttpStatus.NOT_FOUND, e.getMessage());
        } catch (InvalidPasswordException e) {
            return ApiResponse.error(HttpStatus.UNAUTHORIZED, e.getMessage());
        } catch (AccountDisabledException e) {
            return ApiResponse.error(HttpStatus.FORBIDDEN, e.getMessage());
        } catch (Exception e) {
            logger.error("登录异常: {}", e.getMessage(), e);
            return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, "登录失败，请稍后再试");
        }
    }


    /**
     * 修改密码
     */
    @PostMapping("/change-password")
    public ResponseEntity<ApiResponse<Void>> changePassword(@Validated @RequestBody ChangePasswordRequestDTO request) {
        try {
            // 验证新旧密码是否相同
            if (request.getOldPassword().equals(request.getNewPassword())) {
                throw new InvalidInputException("新密码与旧密码不能相同");
            }

            // 验证新密码复杂度
            if (!ValidationUtils.isStrongPassword(request.getNewPassword())) {
                throw new InvalidInputException("密码不合法");
            }

            userService.changePassword(request.getUserId(), request.getOldPassword(), request.getNewPassword());
            return ApiResponse.success(null);
        } catch (UserNotFoundException e) {
            return ApiResponse.error(HttpStatus.NOT_FOUND, e.getMessage());
        } catch (InvalidPasswordException e) {
            return ApiResponse.error(HttpStatus.UNAUTHORIZED, e.getMessage());
        } catch (InvalidInputException e) {
            return ApiResponse.error(HttpStatus.BAD_REQUEST, e.getMessage());
        } catch (Exception e) {
            logger.error("密码更改错误: {}", e.getMessage(), e);
            return ApiResponse.error(HttpStatus.INTERNAL_SERVER_ERROR, "更新密码失败，请稍后再试");
        }
    }
}
